home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / DefaultMutableTreeNode.java < prev    next >
Text File  |  1998-06-30  |  44KB  |  1,492 lines

  1. /*
  2.  * @(#)DefaultMutableTreeNode.java    1.7 98/04/02
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.tree;
  22.    // ISSUE: this class depends on nothing in AWT -- move to java.util?
  23.  
  24. import java.io.*;
  25. import java.util.*;
  26.  
  27.  
  28. /**
  29.  * A <code>DefaultMutableTreeNode</code> is a general-purpose node in a tree data
  30.  * structure. A tree node may have at most one parent and 0 or more children.
  31.  * <code>DefaultMutableTreeNode</code> provides operations for examining and modifying a
  32.  * node's parent and children and also operations for examining the tree that
  33.  * the node is a part of.  A node's tree is the set of all nodes that can be
  34.  * reached by starting at the node and following all the possible links to
  35.  * parents and children.  A node with no parent is the root of its tree; a
  36.  * node with no children is a leaf.  A tree may consist of many subtrees,
  37.  * each node acting as the root for its own subtree.
  38.  * <p>
  39.  * This class provides enumerations for efficiently traversing a tree or
  40.  * subtree in various orders or for following the path between two nodes.
  41.  * A <code>DefaultMutableTreeNode</code> may also hold a reference to a user object, the
  42.  * use of which is left to the user.  Asking a <code>DefaultMutableTreeNode</code> for its
  43.  * string representation with <code>toString()</code> returns the string
  44.  * representation of its user object.
  45.  * <p>
  46.  * <b>This is not a thread safe class.</b>If you intend to use
  47.  * a DefaultMutableTreeNode (or a tree of TreeNodes) in more than one thread, you
  48.  * need to do your own synchronizing. A good convention to adopt is
  49.  * synchronizing on the root node of a tree.
  50.  * <p>
  51.  * While DefaultMutableTreeNode implements the MutableTreeNode interface and
  52.  * will allow you to add in any implementation of MutableTreeNode not all
  53.  * of the methods in DefaultMutableTreeNode will be applicable to all
  54.  * MutableTreeNodes implementations. Especially with some of the enumerations
  55.  * that are provided, using some of these methods assumes the
  56.  * DefaultMutableTreeNode contains only DefaultMutableNode instances. All
  57.  * of the TreeNode/MutableTreeNode methods will behave as defined no
  58.  * matter what implementations are added.
  59.  * <p>
  60.  * Warning: serialized objects of this class will not be compatible with
  61.  * future swing releases.  The current serialization support is appropriate
  62.  * for short term storage or RMI between Swing1.0 applications.  It will
  63.  * not be possible to load serialized Swing1.0 objects with future releases
  64.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  65.  * baseline for the serialized form of Swing objects.
  66.  *
  67.  * @see MutableTreeNode
  68.  *
  69.  * @version 1.7 04/02/98
  70.  * @author Rob Davis
  71.  */
  72. public class DefaultMutableTreeNode extends Object implements Cloneable,
  73.        MutableTreeNode, Serializable
  74. {
  75.  
  76.     /**
  77.      * A null-enumeration class returned when an enumeration of a
  78.      * leaf node's children is requested.
  79.      */
  80.     static public final Enumeration EMPTY_ENUMERATION
  81.     = new Enumeration() {
  82.         public boolean hasMoreElements() { return false; }
  83.         public Object nextElement() {
  84.         throw new NoSuchElementException("No more elements");
  85.         }
  86.     };
  87.  
  88.     /** this node's parent, or null if this node has no parent */
  89.     protected MutableTreeNode   parent;
  90.  
  91.     /** array of children, may be null if this node has no children */
  92.     protected Vector        children;
  93.  
  94.     /** optional user object */
  95.     transient protected Object    userObject;
  96.  
  97.     /** true if the node is able to have children */
  98.     protected boolean        allowsChildren;
  99.  
  100.  
  101.     /**
  102.      * Creates a tree node that has no parent and no children, but which
  103.      * allows children.
  104.      */
  105.     public DefaultMutableTreeNode() {
  106.     this(null);
  107.     }
  108.  
  109.     /**
  110.      * Creates a tree node with no parent, no children, but which allows 
  111.      * children, and initializes it with the specified user object.
  112.      * 
  113.      * @param userObject an Object provided by the user that constitutes
  114.      *                   the node's data
  115.      */
  116.     public DefaultMutableTreeNode(Object userObject) {
  117.     this(userObject, true);
  118.     }
  119.  
  120.     /**
  121.      * Creates a tree node with no parent, no children, initialized with
  122.      * the specified user object, and that allows children only if
  123.      * specified.
  124.      * 
  125.      * @param userObject an Object provided by the user that constitutes
  126.      *        the node's data
  127.      * @param allowsChildren if true, the node is allowed to have child
  128.      *        nodes -- otherwise, it is always a leaf node
  129.      */
  130.     public DefaultMutableTreeNode(Object userObject, boolean allowsChildren) {
  131.     super();
  132.     parent = null;
  133.     this.allowsChildren = allowsChildren;
  134.     this.userObject = userObject;
  135.     }
  136.  
  137.  
  138.     //
  139.     //  Primitives
  140.     //
  141.  
  142.     /**
  143.      * Removes <code>newChild</code> from its present parent (if it has a
  144.      * parent), sets the child's parent to this node, and then adds the child
  145.      * to this node's child array at index <code>childIndex</code>.
  146.      * <code>newChild</code> must not be null and must not be an ancestor of
  147.      * this node.
  148.      *
  149.      * @param    newChild    the MutableTreeNode to insert under this node
  150.      * @param    childIndex    the index in this node's child array
  151.      *                where this node is to be inserted
  152.      * @exception    ArrayIndexOutOfBoundsException    if
  153.      *                <code>childIndex</code> is out of bounds
  154.      * @exception    IllegalArgumentException    if
  155.      *                <code>newChild</code> is null or is an
  156.      *                ancestor of this node
  157.      * @exception    IllegalStateException    if this node does not allow
  158.      *                        children
  159.      * @see    #isNodeDescendant
  160.      */
  161.     public void insert(MutableTreeNode newChild, int childIndex) {
  162.     if (!allowsChildren) {
  163.         throw new IllegalStateException("node does not allow children");
  164.     } else if (newChild == null) {
  165.         throw new IllegalArgumentException("new child is null");
  166.     } else if (isNodeAncestor(newChild)) {
  167.         throw new IllegalArgumentException("new child is an ancestor");
  168.     }
  169.  
  170.         MutableTreeNode oldParent = (MutableTreeNode)newChild.getParent();
  171.  
  172.         if (oldParent != null) {
  173.         oldParent.remove(newChild);
  174.         }
  175.         newChild.setParent(this);
  176.         if (children == null) {
  177.         children = new Vector();
  178.         }
  179.         children.insertElementAt(newChild, childIndex);
  180.     }
  181.  
  182.     /**
  183.      * Removes the child at the specified index from this node's children
  184.      * and sets that node's parent to null. The child node to remove
  185.      * must be a <code>MutableTreeNode</code>.
  186.      *
  187.      * @param    childIndex    the index in this node's child array
  188.      *                of the child to remove
  189.      * @exception    ArrayIndexOutOfBoundsException    if
  190.      *                <code>childIndex</code> is out of bounds
  191.      */
  192.     public void remove(int childIndex) {
  193.     MutableTreeNode child = (MutableTreeNode)getChildAt(childIndex);
  194.     children.removeElementAt(childIndex);
  195.     child.setParent(null);
  196.     }
  197.  
  198.     /**
  199.      * Sets this node's parent to <code>newParent</code> but does not 
  200.      * change the parent's child array.  This method is called from
  201.      * <code>insert()</code> and <code>remove()</code> to
  202.      * reassign a child's parent, it should not be messaged from anywhere
  203.      * else.
  204.      *
  205.      * @param    newParent    this node's new parent
  206.      */
  207.     public void setParent(MutableTreeNode newParent) {
  208.     parent = newParent;
  209.     }
  210.  
  211.     /**
  212.      * Returns this node's parent or null if this node has no parent.
  213.      *
  214.      * @return    this node's parent TreeNode, or null if this node has no parent
  215.      */
  216.     public TreeNode getParent() {
  217.     return parent;
  218.     }
  219.  
  220.     /**
  221.      * Returns the child at the specified index in this node's child array.
  222.      *
  223.      * @param    index    an index into this node's child array
  224.      * @exception    ArrayIndexOutOfBoundsException    if <code>index</code>
  225.      *                        is out of bounds
  226.      * @return    the TreeNode in this node's child array at  the specified index
  227.      */
  228.     public TreeNode getChildAt(int index) {
  229.     if (children == null) {
  230.         throw new ArrayIndexOutOfBoundsException("node has no children");
  231.     }
  232.     return (TreeNode)children.elementAt(index);
  233.     }
  234.  
  235.     /**
  236.      * Returns the number of children of this node.
  237.      *
  238.      * @return    an int giving the number of children of this node
  239.      */
  240.     public int getChildCount() {
  241.     if (children == null) {
  242.         return 0;
  243.     } else {
  244.         return children.size();
  245.     }
  246.     }
  247.  
  248.     /**
  249.      * Returns the index of the specified child in this node's child array.
  250.      * If the specified node is not a child of this node, returns
  251.      * <code>-1</code>.  This method performs a linear search and is O(n)
  252.      * where n is the number of children.
  253.      *
  254.      * @param    aChild    the TreeNode to search for among this node's children
  255.      * @exception    IllegalArgumentException    if <code>aChild</code>
  256.      *                            is null
  257.      * @return    an int giving the index of the node in this node's child 
  258.      *          array, or <code>-1</code> if the specified node is a not
  259.      *          a child of this node
  260.      */
  261.     public int getIndex(TreeNode aChild) {
  262.     if (aChild == null) {
  263.         throw new IllegalArgumentException("argument is null");
  264.     }
  265.  
  266.     if (!isNodeChild(aChild)) {
  267.         return -1;
  268.     }
  269.     return children.indexOf(aChild);    // linear search
  270.     }
  271.  
  272.     /**
  273.      * Creates and returns a forward-order enumeration of this node's
  274.      * children.  Modifying this node's child array invalidates any child
  275.      * enumerations created before the modification.
  276.      *
  277.      * @return    an Enumeration of this node's children
  278.      */
  279.     public Enumeration children() {
  280.     if (children == null) {
  281.         return EMPTY_ENUMERATION;
  282.     } else {
  283.         return children.elements();
  284.     }
  285.     }
  286.  
  287.     /**
  288.      * Determines whether or not this node is allowed to have children. 
  289.      * If <code>allows</code> is false, all of this node's children are
  290.      * removed.
  291.      * <p>
  292.      * Note: By default, a node allows children.
  293.      *
  294.      * @param    allows    true if this node is allowed to have children
  295.      */
  296.     public void setAllowsChildren(boolean allows) {
  297.     if (allows != allowsChildren) {
  298.         allowsChildren = allows;
  299.         if (!allowsChildren) {
  300.         removeAllChildren();
  301.         }
  302.     }
  303.     }
  304.  
  305.     /**
  306.      * Returns true if this node is allowed to have children.
  307.      *
  308.      * @return    true if this node allows children, else false
  309.      */
  310.     public boolean getAllowsChildren() {
  311.     return allowsChildren;
  312.     }
  313.  
  314.     /**
  315.      * Sets the user object for this node to <code>userObject</code>.
  316.      *
  317.      * @param    userObject    the Object that constitutes this node's 
  318.      *                          user-specified data
  319.      * @see    #getUserObject
  320.      * @see    #toString
  321.      */
  322.     public void setUserObject(Object userObject) {
  323.     this.userObject = userObject;
  324.     }
  325.  
  326.     /**
  327.      * Returns this node's user object.
  328.      *
  329.      * @return    the Object stored at this node by the user
  330.      * @see    #setUserObject
  331.      * @see    #toString
  332.      */
  333.     public Object getUserObject() {
  334.     return userObject;
  335.     }
  336.  
  337.  
  338.     //
  339.     //  Derived methods
  340.     //
  341.  
  342.     /**
  343.      * Removes the subtree rooted at this node from the tree, giving this
  344.      * node a null parent.  Does nothing if this node is the root of its
  345.      * tree.
  346.      */
  347.     public void removeFromParent() {
  348.     MutableTreeNode parent = (MutableTreeNode)getParent();
  349.     if (parent != null) {
  350.         parent.remove(this);
  351.     }
  352.     }
  353.  
  354.     /**
  355.      * Removes <code>aChild</code> from this node's child array, giving it a
  356.      * null parent.
  357.      *
  358.      * @param    aChild    a child of this node to remove
  359.      * @exception    IllegalArgumentException    if <code>aChild</code>
  360.      *                    is null or is not a child of this node
  361.      */
  362.     public void remove(MutableTreeNode aChild) {
  363.     if (aChild == null) {
  364.         throw new IllegalArgumentException("argument is null");
  365.     }
  366.  
  367.     if (!isNodeChild(aChild)) {
  368.         throw new IllegalArgumentException("argument is not a child");
  369.     }
  370.     remove(getIndex(aChild));    // linear search
  371.     }
  372.  
  373.     /**
  374.      * Removes all of this node's children, setting their parents to null.
  375.      * If this node has no children, this method does nothing.
  376.      */
  377.     public void removeAllChildren() {
  378.     for (int i = getChildCount()-1; i >= 0; i--) {
  379.         remove(i);
  380.     }
  381.     }
  382.  
  383.     /**
  384.      * Removes <code>newChild</code> from its parent and makes it a child of
  385.      * this node by adding it to the end of this node's child array.
  386.      *
  387.      * @see        #insert
  388.      * @param    newChild    node to add as a child of this node
  389.      * @exception    IllegalArgumentException    if <code>newChild</code>
  390.      *                        is null
  391.      * @exception    IllegalStateException    if this node does not allow
  392.      *                        children
  393.      */
  394.     public void add(MutableTreeNode newChild) {
  395.     if(newChild != null && newChild.getParent() == this)
  396.         insert(newChild, getChildCount() - 1);
  397.     else
  398.         insert(newChild, getChildCount());
  399.     }
  400.  
  401.  
  402.  
  403.     //
  404.     //  Tree Queries
  405.     //
  406.  
  407.     /**
  408.      * Returns true if <code>anotherNode</code> is an ancestor of this node
  409.      * -- if it is this node, this node's parent, or an ancestor of this
  410.      * node's parent.  (Note that a node is considered an ancestor of itself.)
  411.      * If <code>anotherNode</code> is null, this method returns false.  This
  412.      * operation is at worst O(h) where h is the distance from the root to
  413.      * this node.
  414.      *
  415.      * @see        #isNodeDescendant
  416.      * @see        #getSharedAncestor
  417.      * @param    anotherNode    node to test as an ancestor of this node
  418.      * @return    true if this node is a descendant of <code>anotherNode</code>
  419.      */
  420.     public boolean isNodeAncestor(TreeNode anotherNode) {
  421.     if (anotherNode == null) {
  422.         return false;
  423.     }
  424.  
  425.     TreeNode ancestor = this;
  426.  
  427.     do {
  428.         if (ancestor == anotherNode) {
  429.         return true;
  430.         }
  431.     } while((ancestor = ancestor.getParent()) != null);
  432.  
  433.     return false;
  434.     }
  435.  
  436.     /**
  437.      * Returns true if <code>anotherNode</code> is a descendant of this node
  438.      * -- if it is this node, one of this node's children, or a descendant of
  439.      * one of this node's children.  Note that a node is considered a
  440.      * descendant of itself.  If <code>anotherNode</code> is null, returns
  441.      * false.  This operation is at worst O(h) where h is the distance from the
  442.      * root to <code>anotherNode</code>.
  443.      *
  444.      * @see    #isNodeAncestor
  445.      * @see    #getSharedAncestor
  446.      * @param    anotherNode    node to test as descendant of this node
  447.      * @return    true if this node is an ancestor of <code>anotherNode</code>
  448.      */
  449.     public boolean isNodeDescendant(DefaultMutableTreeNode anotherNode) {
  450.     if (anotherNode == null)
  451.         return false;
  452.  
  453.     return anotherNode.isNodeAncestor(this);
  454.     }
  455.  
  456.     /**
  457.      * Returns the nearest common ancestor to this node and <code>aNode</code>.
  458.      * Returns null, if no such ancestor exists -- if this node and
  459.      * <code>aNode</code> are in different trees or if <code>aNode</code> is
  460.      * null.  A node is considered an ancestor of itself.
  461.      *
  462.      * @see    #isNodeAncestor
  463.      * @see    #isNodeDescendant
  464.      * @param    aNode    node to find common ancestor with
  465.      * @return    nearest ancestor common to this node and <code>aNode</code>,
  466.      *        or null if none
  467.      */
  468.     public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) {
  469.     if (aNode == this) {
  470.         return this;
  471.     } else if (aNode == null) {
  472.         return null;
  473.     }
  474.  
  475.     int        level1, level2, diff;
  476.     TreeNode    node1, node2;
  477.     
  478.     level1 = getLevel();
  479.     level2 = aNode.getLevel();
  480.     
  481.     if (level2 > level1) {
  482.         diff = level2 - level1;
  483.         node1 = aNode;
  484.         node2 = this;
  485.     } else {
  486.         diff = level1 - level2;
  487.         node1 = this;
  488.         node2 = aNode;
  489.     }
  490.  
  491.     // Go up the tree until the nodes are at the same level
  492.     while (diff > 0) {
  493.         node1 = node1.getParent();
  494.         diff--;
  495.     }
  496.     
  497.     // Move up the tree until we find a common ancestor.  Since we know
  498.     // that both nodes are at the same level, we won't cross paths
  499.     // unknowingly (if there is a common ancestor, both nodes hit it in
  500.     // the same iteration).
  501.     
  502.     do {
  503.         if (node1 == node2) {
  504.         return node1;
  505.         }
  506.         node1 = node1.getParent();
  507.         node2 = node2.getParent();
  508.     } while (node1 != null);// only need to check one -- they're at the
  509.     // same level so if one is null, the other is
  510.     
  511.     if (node1 != null || node2 != null) {
  512.         throw new InternalError ("nodes should be null");
  513.     }
  514.     
  515.     return null;
  516.     }
  517.  
  518.  
  519.     /**
  520.      * Returns true if and only if <code>aNode</code> is in the same tree
  521.      * as this node.  Returns false if <code>aNode</code> is null.
  522.      *
  523.      * @see    #getSharedAncestor
  524.      * @see    #getRoot
  525.      * @return    true if <code>aNode</code> is in the same tree as this node;
  526.      *        false if <code>aNode</code> is null
  527.      */
  528.     public boolean isNodeRelated(DefaultMutableTreeNode aNode) {
  529.     return (aNode != null) && (getRoot() == aNode.getRoot());
  530.     }
  531.  
  532.  
  533.     /**
  534.      * Returns the depth of the tree rooted at this node -- the longest
  535.      * distance from this node to a leaf.  If this node has no children,
  536.      * returns 0.  This operation is much more expensive than
  537.      * <code>getLevel()</code> because it must effectively traverse the entire
  538.      * tree rooted at this node.
  539.      *
  540.      * @see    #getLevel
  541.      * @return    the depth of the tree whose root is this node
  542.      */
  543.     public int getDepth() {
  544.     Object    last = null;
  545.     Enumeration    enum = breadthFirstEnumeration();
  546.     
  547.     while (enum.hasMoreElements()) {
  548.         last = enum.nextElement();
  549.     }
  550.     
  551.     if (last == null) {
  552.         throw new InternalError ("nodes should be null");
  553.     }
  554.     
  555.     return ((DefaultMutableTreeNode)last).getLevel() - getLevel();
  556.     }
  557.  
  558.  
  559.  
  560.     /**
  561.      * Returns the number of levels above this node -- the distance from
  562.      * the root to this node.  If this node is the root, returns 0.
  563.      *
  564.      * @see    #getDepth
  565.      * @return    the number of levels above this node
  566.      */
  567.     public int getLevel() {
  568.     TreeNode ancestor;
  569.     int levels = 0;
  570.  
  571.     ancestor = this;
  572.     while((ancestor = ancestor.getParent()) != null){
  573.         levels++;
  574.     }
  575.  
  576.     return levels;
  577.     }
  578.  
  579.  
  580.     /**
  581.       * Returns the path from the root, to get to this node.  The last
  582.       * element in the path is this node.
  583.       *
  584.       * @return an array of TreeNode objects giving the path, where the
  585.       *         first element in the path is the root and the last
  586.       *         element is this node.
  587.       */
  588.     public TreeNode[] getPath() {
  589.     return getPathToRoot(this, 0);
  590.     }
  591.  
  592.     /**
  593.      * Builds the parents of node up to and including the root node,
  594.      * where the original node is the last element in the returned array.
  595.      * The length of the returned array gives the node's depth in the
  596.      * tree.
  597.      * 
  598.      * @param aNode  the TreeNode to get the path for
  599.      * @param depth  an int giving the number of steps already taken towards
  600.      *        the root (on recursive calls), used to size the returned array
  601.      * @return an array of TreeNodes giving the path from the root to the
  602.      *         specified node 
  603.      */
  604.     protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
  605.     TreeNode[]              retNodes;
  606.  
  607.     /* Check for null, in case someone passed in a null node, or
  608.        they passed in an element that isn't rooted at root. */
  609.     if(aNode == null) {
  610.         if(depth == 0)
  611.         return null;
  612.         else
  613.         retNodes = new TreeNode[depth];
  614.     }
  615.     else {
  616.         depth++;
  617.         retNodes = getPathToRoot(aNode.getParent(), depth);
  618.         retNodes[retNodes.length - depth] = aNode;
  619.     }
  620.     return retNodes;
  621.     }
  622.  
  623.     /**
  624.       * Returns the user object path, from the root, to get to this node.
  625.       * If some of the TreeNodes in the path have null user objects, the
  626.       * returned path will contain nulls.
  627.       */
  628.     public Object[] getUserObjectPath() {
  629.     TreeNode[]          realPath = getPath();
  630.     Object[]            retPath = new Object[realPath.length];
  631.  
  632.     for(int counter = 0; counter < realPath.length; counter++)
  633.         retPath[counter] = ((DefaultMutableTreeNode)realPath[counter])
  634.                        .getUserObject();
  635.     return retPath;
  636.     }
  637.  
  638.     /**
  639.      * Returns the root of the tree that contains this node.  The root is
  640.      * the ancestor with a null parent.
  641.      *
  642.      * @see    #isNodeAncestor
  643.      * @return    the root of the tree that contains this node
  644.      */
  645.     public TreeNode getRoot() {
  646.     TreeNode ancestor = this;
  647.     TreeNode previous;
  648.  
  649.     do {
  650.         previous = ancestor;
  651.         ancestor = ancestor.getParent();
  652.     } while (ancestor != null);
  653.  
  654.     return previous;
  655.     }
  656.  
  657.  
  658.     /**
  659.      * Returns true if this node is the root of the tree.  The root is
  660.      * the only node in the tree with a null parent; every tree has exactly
  661.      * one root.
  662.      *
  663.      * @return    true if this node is the root of its tree
  664.      */
  665.     public boolean isRoot() {
  666.     return getParent() == null;
  667.     }
  668.  
  669.  
  670.     /**
  671.      * Returns the node that follows this node in a preorder traversal of this
  672.      * node's tree.  Returns null if this node is the last node of the
  673.      * traversal.  This is an inefficient way to traverse the entire tree; use
  674.      * an enumeration, instead.
  675.      *
  676.      * @see    #preorderEnumeration
  677.      * @return    the node that follows this node in a preorder traversal, or
  678.      *        null if this node is last
  679.      */
  680.     public DefaultMutableTreeNode getNextNode() {
  681.     if (getChildCount() == 0) {
  682.         // No children, so look for nextSibling
  683.         DefaultMutableTreeNode nextSibling = getNextSibling();
  684.  
  685.         if (nextSibling == null) {
  686.         DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)getParent();
  687.  
  688.         do {
  689.             if (aNode == null) {
  690.             return null;
  691.             }
  692.  
  693.             nextSibling = aNode.getNextSibling();
  694.             if (nextSibling != null) {
  695.             return nextSibling;
  696.             }
  697.  
  698.             aNode = (DefaultMutableTreeNode)aNode.getParent();
  699.         } while(true);
  700.         } else {
  701.         return nextSibling;
  702.         }
  703.     } else {
  704.         return (DefaultMutableTreeNode)getChildAt(0);
  705.     }
  706.     }
  707.  
  708.  
  709.     /**
  710.      * Returns the node that precedes this node in a preorder traversal of
  711.      * this node's tree.  Returns null if this node is the first node of the
  712.      * traveral -- the root of the tree.  This is an inefficient way to
  713.      * traverse the entire tree; use an enumeration, instead.
  714.      *
  715.      * @see    #preorderEnumeration
  716.      * @return    the node that precedes this node in a preorder traversal, or
  717.      *        null if this node is the first
  718.      */
  719.     public DefaultMutableTreeNode getPreviousNode() {
  720.     DefaultMutableTreeNode previousSibling;
  721.     DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  722.  
  723.     if (myParent == null) {
  724.         return null;
  725.     }
  726.  
  727.     previousSibling = getPreviousSibling();
  728.  
  729.     if (previousSibling != null) {
  730.         if (previousSibling.getChildCount() == 0)
  731.         return previousSibling;
  732.         else
  733.         return previousSibling.getLastLeaf();
  734.     } else {
  735.         return myParent;
  736.     }
  737.     }
  738.  
  739.     /**
  740.      * Creates and returns an enumeration that traverses the subtree rooted at
  741.      * this node in preorder.  The first node returned by the enumeration's
  742.      * <code>nextElement()</code> method is this node.<P>
  743.      *
  744.      * Modifying the tree by inserting, removing, or moving a node invalidates
  745.      * any enumerations created before the modification.
  746.      *
  747.      * @see    #postorderEnumeration
  748.      * @return    an enumeration for traversing the tree in preorder
  749.      */
  750.     public Enumeration preorderEnumeration() {
  751.     return new PreorderEnumeration(this);
  752.     }
  753.  
  754.     /**
  755.      * Creates and returns an enumeration that traverses the subtree rooted at
  756.      * this node in postorder.  The first node returned by the enumeration's
  757.      * <code>nextElement()</code> method is the leftmost leaf.  This is the
  758.      * same as a depth-first traversal.<P>
  759.      *
  760.      * Modifying the tree by inserting, removing, or moving a node invalidates
  761.      * any enumerations created before the modification.
  762.      *
  763.      * @see    #depthFirstEnumeration
  764.      * @see    #preorderEnumeration
  765.      * @return    an enumeration for traversing the tree in postorder
  766.      */
  767.     public Enumeration postorderEnumeration() {
  768.     return new PostorderEnumeration(this);
  769.     }
  770.  
  771.     /**
  772.      * Creates and returns an enumeration that traverses the subtree rooted at
  773.      * this node in breadth-first order.  The first node returned by the
  774.      * enumeration's <code>nextElement()</code> method is this node.<P>
  775.      *
  776.      * Modifying the tree by inserting, removing, or moving a node invalidates
  777.      * any enumerations created before the modification.
  778.      *
  779.      * @see    #depthFirstEnumeration
  780.      * @return    an enumeration for traversing the tree in breadth-first order
  781.      */
  782.     public Enumeration breadthFirstEnumeration() {
  783.     return new BreadthFirstEnumeration(this);
  784.     }
  785.  
  786.     /**
  787.      * Creates and returns an enumeration that traverses the subtree rooted at
  788.      * this node in depth-first order.  The first node returned by the
  789.      * enumeration's <code>nextElement()</code> method is the leftmost leaf.
  790.      * This is the same as a postorder traversal.<P>
  791.      *
  792.      * Modifying the tree by inserting, removing, or moving a node invalidates
  793.      * any enumerations created before the modification.
  794.      *
  795.      * @see    #breadthFirstEnumeration
  796.      * @see    #postorderEnumeration
  797.      * @return    an enumeration for traversing the tree in depth-first order
  798.      */
  799.     public Enumeration depthFirstEnumeration() {
  800.     return postorderEnumeration();
  801.     }
  802.  
  803.     /**
  804.      * Creates and returns an enumeration that follows the path from
  805.      * <code>ancestor</code> to this node.  The enumeration's
  806.      * <code>nextElement()</code> method first returns <code>ancestor</code>,
  807.      * then the child of <code>ancestor</code> that is an ancestor of this
  808.      * node, and so on, and finally returns this node.  Creation of the
  809.      * enumeration is O(m) where m is the number of nodes between this node
  810.      * and <code>ancestor</code>, inclusive.  Each <code>nextElement()</code>
  811.      * message is O(1).<P>
  812.      *
  813.      * Modifying the tree by inserting, removing, or moving a node invalidates
  814.      * any enumerations created before the modification.
  815.      *
  816.      * @see        #isNodeAncestor
  817.      * @see        #isNodeDescendant
  818.      * @exception    IllegalArgumentException if <code>ancestor</code> is
  819.      *                        not an ancestor of this node
  820.      * @return    an enumeration for following the path from an ancestor of
  821.      *        this node to this one
  822.      */
  823.     public Enumeration pathFromAncestorEnumeration(TreeNode ancestor){
  824.     return new PathBetweenNodesEnumeration(ancestor, this);
  825.     }
  826.  
  827.  
  828.     //
  829.     //  Child Queries
  830.     //
  831.  
  832.     /**
  833.      * Returns true if <code>aNode</code> is a child of this node.  If
  834.      * <code>aNode</code> is null, this method returns false.
  835.      *
  836.      * @return    true if <code>aNode</code> is a child of this node; false if 
  837.      *          <code>aNode</code> is null
  838.      */
  839.     public boolean isNodeChild(TreeNode aNode) {
  840.     boolean retval;
  841.  
  842.     if (aNode == null) {
  843.         retval = false;
  844.     } else {
  845.         if (getChildCount() == 0) {
  846.         retval = false;
  847.         } else {
  848.         retval = (aNode.getParent() == this);
  849.         }
  850.     }
  851.  
  852.     return retval;
  853.     }
  854.  
  855.  
  856.     /**
  857.      * Returns this node's first child.  If this node has no children,
  858.      * throws NoSuchElementException.
  859.      *
  860.      * @return    the first child of this node
  861.      * @exception    NoSuchElementException    if this node has no children
  862.      */
  863.     public TreeNode getFirstChild() {
  864.     if (getChildCount() == 0) {
  865.         throw new NoSuchElementException("node has no children");
  866.     }
  867.     return getChildAt(0);
  868.     }
  869.  
  870.  
  871.     /**
  872.      * Returns this node's last child.  If this node has no children,
  873.      * throws NoSuchElementException.
  874.      *
  875.      * @return    the last child of this node
  876.      * @exception    NoSuchElementException    if this node has no children
  877.      */
  878.     public TreeNode getLastChild() {
  879.     if (getChildCount() == 0) {
  880.         throw new NoSuchElementException("node has no children");
  881.     }
  882.     return getChildAt(getChildCount()-1);
  883.     }
  884.  
  885.  
  886.     /**
  887.      * Returns the child in this node's child array that immediately
  888.      * follows <code>aChild</code>, which must be a child of this node.  If
  889.      * <code>aChild</code> is the last child, returns null.  This method
  890.      * performs a linear search of this node's children for
  891.      * <code>aChild</code> and is O(n) where n is the number of children; to
  892.      * traverse the entire array of children, use an enumeration instead.
  893.      *
  894.      * @see        #children
  895.      * @exception    IllegalArgumentException if <code>aChild</code> is
  896.      *                    null or is not a child of this node
  897.      * @return    the child of this node that immediately follows
  898.      *        <code>aChild</code>
  899.      */
  900.     public TreeNode getChildAfter(TreeNode aChild) {
  901.     if (aChild == null) {
  902.         throw new IllegalArgumentException("argument is null");
  903.     }
  904.  
  905.     int index = getIndex(aChild);        // linear search
  906.  
  907.     if (index == -1) {
  908.         throw new IllegalArgumentException("node is not a child");
  909.     }
  910.  
  911.     if (index < getChildCount() - 1) {
  912.         return getChildAt(index + 1);
  913.     } else {
  914.         return null;
  915.     }
  916.     }
  917.  
  918.  
  919.     /**
  920.      * Returns the child in this node's child array that immediately
  921.      * precedes <code>aChild</code>, which must be a child of this node.  If
  922.      * <code>aChild</code> is the first child, returns null.  This method
  923.      * performs a linear search of this node's children for <code>aChild</code>
  924.      * and is O(n) where n is the number of children.
  925.      *
  926.      * @exception    IllegalArgumentException if <code>aChild</code> is null
  927.      *                        or is not a child of this node
  928.      * @return    the child of this node that immediately precedes
  929.      *        <code>aChild</code>
  930.      */
  931.     public TreeNode getChildBefore(TreeNode aChild) {
  932.     if (aChild == null) {
  933.         throw new IllegalArgumentException("argument is null");
  934.     }
  935.  
  936.     int index = getIndex(aChild);        // linear search
  937.  
  938.     if (index == -1) {
  939.         throw new IllegalArgumentException("argument is not a child");
  940.     }
  941.  
  942.     if (index > 0) {
  943.         return getChildAt(index - 1);
  944.     } else {
  945.         return null;
  946.     }
  947.     }
  948.  
  949.  
  950.     //
  951.     //  Sibling Queries
  952.     //
  953.  
  954.  
  955.     /**
  956.      * Returns true if <code>anotherNode</code> is a sibling of (has the
  957.      * same parent as) this node.  A node is its own sibling.  If
  958.      * <code>anotherNode</code> is null, returns false.
  959.      *
  960.      * @param    anotherNode    node to test as sibling of this node
  961.      * @return    true if <code>anotherNode</code> is a sibling of this node
  962.      */
  963.     public boolean isNodeSibling(TreeNode anotherNode) {
  964.     boolean retval;
  965.  
  966.     if (anotherNode == null) {
  967.         retval = false;
  968.     } else if (anotherNode == this) {
  969.         retval = true;
  970.     } else {
  971.         TreeNode  myParent = getParent();
  972.         retval = (myParent != null && myParent == anotherNode.getParent());
  973.  
  974.         if (retval && !((DefaultMutableTreeNode)getParent())
  975.                    .isNodeChild(anotherNode)) {
  976.         throw new InternalError("sibling has different parent");
  977.         }
  978.     }
  979.  
  980.     return retval;
  981.     }
  982.  
  983.  
  984.     /**
  985.      * Returns the number of siblings of this node.  A node is its own sibling
  986.      * (if it has no parent or no siblings, this method returns
  987.      * <code>1</code>).
  988.      *
  989.      * @return    the number of siblings of this node
  990.      */
  991.     public int getSiblingCount() {
  992.     TreeNode myParent = getParent();
  993.  
  994.     if (myParent == null) {
  995.         return 1;
  996.     } else {
  997.         return myParent.getChildCount();
  998.     }
  999.     }
  1000.  
  1001.  
  1002.     /**
  1003.      * Returns the next sibling of this node in the parent's children array.
  1004.      * Returns null if this node has no parent or is the parent's last child.
  1005.      * This method performs a linear search that is O(n) where n is the number
  1006.      * of children; to traverse the entire array, use the parent's child
  1007.      * enumeration instead.
  1008.      *
  1009.      * @see    #children
  1010.      * @return    the sibling of this node that immediately follows this node
  1011.      */
  1012.     public DefaultMutableTreeNode getNextSibling() {
  1013.     DefaultMutableTreeNode retval;
  1014.  
  1015.     DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  1016.  
  1017.     if (myParent == null) {
  1018.         retval = null;
  1019.     } else {
  1020.         retval = (DefaultMutableTreeNode)myParent.getChildAfter(this);    // linear search
  1021.     }
  1022.  
  1023.     if (retval != null && !isNodeSibling(retval)) {
  1024.         throw new InternalError("child of parent is not a sibling");
  1025.     }
  1026.  
  1027.     return retval;
  1028.     }
  1029.  
  1030.  
  1031.     /**
  1032.      * Returns the previous sibling of this node in the parent's children
  1033.      * array.  Returns null if this node has no parent or is the parent's
  1034.      * first child.  This method performs a linear search that is O(n) where n
  1035.      * is the number of children.
  1036.      *
  1037.      * @return    the sibling of this node that immediately precedes this node
  1038.      */
  1039.     public DefaultMutableTreeNode getPreviousSibling() {
  1040.     DefaultMutableTreeNode retval;
  1041.  
  1042.     DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  1043.  
  1044.     if (myParent == null) {
  1045.         retval = null;
  1046.     } else {
  1047.         retval = (DefaultMutableTreeNode)myParent.getChildBefore(this);    // linear search
  1048.     }
  1049.  
  1050.     if (retval != null && !isNodeSibling(retval)) {
  1051.         throw new InternalError("child of parent is not a sibling");
  1052.     }
  1053.  
  1054.     return retval;
  1055.     }
  1056.  
  1057.  
  1058.  
  1059.     //
  1060.     //  Leaf Queries
  1061.     //
  1062.  
  1063.     /**
  1064.      * Returns true if this node has no children.  To distinguish between
  1065.      * nodes that have no children and nodes that <i>cannot</i> have
  1066.      * children (e.g. to distinguish files from empty directories), use this
  1067.      * method in conjunction with <code>getAllowsChildren</code>
  1068.      *
  1069.      * @see    #getAllowsChildren
  1070.      * @return    true if this node has no children
  1071.      */
  1072.     public boolean isLeaf() {
  1073.     return (getChildCount() == 0);
  1074.     }
  1075.  
  1076.  
  1077.     /**
  1078.      * Finds and returns the first leaf that is a descendant of this node --
  1079.      * either this node or its first child's first leaf.
  1080.      * Returns this node if it is a leaf.
  1081.      *
  1082.      * @see    #isLeaf
  1083.      * @see    #isNodeDescendant
  1084.      * @return    the first leaf in the subtree rooted at this node
  1085.      */
  1086.     public DefaultMutableTreeNode getFirstLeaf() {
  1087.     DefaultMutableTreeNode node = this;
  1088.  
  1089.     while (!node.isLeaf()) {
  1090.         node = (DefaultMutableTreeNode)node.getFirstChild();
  1091.     }
  1092.  
  1093.     return node;
  1094.     }
  1095.  
  1096.  
  1097.     /**
  1098.      * Finds and returns the last leaf that is a descendant of this node --
  1099.      * either this node or its last child's last leaf. 
  1100.      * Returns this node if it is a leaf.
  1101.      *
  1102.      * @see    #isLeaf
  1103.      * @see    #isNodeDescendant
  1104.      * @return    the last leaf in the subtree rooted at this node
  1105.      */
  1106.     public DefaultMutableTreeNode getLastLeaf() {
  1107.     DefaultMutableTreeNode node = this;
  1108.  
  1109.     while (!node.isLeaf()) {
  1110.         node = (DefaultMutableTreeNode)node.getLastChild();
  1111.     }
  1112.  
  1113.     return node;
  1114.     }
  1115.  
  1116.  
  1117.     /**
  1118.      * Returns the leaf after this node or null if this node is the
  1119.      * last leaf in the tree.
  1120.      * <p>
  1121.      * In this implementation of the <code>MutableNode</code> interface,
  1122.      * this operation is very inefficient. In order to determine the
  1123.      * next node, this method first performs a linear search in the 
  1124.      * parent's child-list in order to find the current node. 
  1125.      * <p>
  1126.      * That implementation makes the operation suitable for short
  1127.      * traversals from a known position. But to traverse all of the 
  1128.      * leaves in the tree, you should use <code>depthFirstEnumeration</code>
  1129.      * to enumerate the nodes in the tree and use <code>isLeaf</code>
  1130.      * on each node to determine which are leaves.
  1131.      *
  1132.      * @see    #depthFirstEnumeration
  1133.      * @see    #isLeaf
  1134.      * @return    returns the next leaf past this node
  1135.      */
  1136.     public DefaultMutableTreeNode getNextLeaf() {
  1137.     DefaultMutableTreeNode nextSibling;
  1138.     DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  1139.  
  1140.     if (myParent == null)
  1141.         return null;
  1142.  
  1143.     nextSibling = getNextSibling();    // linear search
  1144.  
  1145.     if (nextSibling != null)
  1146.         return nextSibling.getFirstLeaf();
  1147.  
  1148.     return myParent.getNextLeaf();    // tail recursion
  1149.     }
  1150.  
  1151.  
  1152.     /**
  1153.      * Returns the leaf before this node or null if this node is the
  1154.      * first leaf in the tree.
  1155.      * <p>
  1156.      * In this implementation of the <code>MutableNode</code> interface,
  1157.      * this operation is very inefficient. In order to determine the
  1158.      * previous node, this method first performs a linear search in the 
  1159.      * parent's child-list in order to find the current node. 
  1160.      * <p>
  1161.      * That implementation makes the operation suitable for short
  1162.      * traversals from a known position. But to traverse all of the 
  1163.      * leaves in the tree, you should use <code>depthFirstEnumeration</code>
  1164.      * to enumerate the nodes in the tree and use <code>isLeaf</code>
  1165.      * on each node to determine which are leaves.
  1166.      *
  1167.      * @see        #depthFirstEnumeration
  1168.      * @see        #isLeaf
  1169.      * @return    returns the leaf before this node
  1170.      */
  1171.     public DefaultMutableTreeNode getPreviousLeaf() {
  1172.     DefaultMutableTreeNode previousSibling;
  1173.     DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  1174.  
  1175.     if (myParent == null)
  1176.         return null;
  1177.  
  1178.     previousSibling = getPreviousSibling();    // linear search
  1179.  
  1180.     if (previousSibling != null)
  1181.         return previousSibling.getLastLeaf();
  1182.  
  1183.     return myParent.getPreviousLeaf();        // tail recursion
  1184.     }
  1185.  
  1186.  
  1187.     /**
  1188.      * Returns the total number of leaves that are descendants of this node.
  1189.      * If this node is a leaf, returns <code>1</code>.  This method is O(n)
  1190.      * where n is the number of descendants of this node.
  1191.      *
  1192.      * @see    #isNodeAncestor
  1193.      * @return    the number of leaves beneath this node
  1194.      */
  1195.     public int getLeafCount() {
  1196.     int count = 0;
  1197.  
  1198.     TreeNode node;
  1199.     Enumeration enum = breadthFirstEnumeration(); // order matters not
  1200.  
  1201.     while (enum.hasMoreElements()) {
  1202.         node = (TreeNode)enum.nextElement();
  1203.         if (node.isLeaf()) {
  1204.         count++;
  1205.         }
  1206.     }
  1207.  
  1208.     if (count < 1) {
  1209.         throw new InternalError("tree has zero leaves");
  1210.     }
  1211.  
  1212.     return count;
  1213.     }
  1214.  
  1215.  
  1216.     //
  1217.     //  Overrides
  1218.     //
  1219.  
  1220.     /**
  1221.      * Returns the result of sending <code>toString()</code> to this node's
  1222.      * user object, or null if this node has no user object.
  1223.      *
  1224.      * @see    #getUserObject
  1225.      */
  1226.     public String toString() {
  1227.     if (userObject == null) {
  1228.         return null;
  1229.     } else {
  1230.         return userObject.toString();
  1231.     }
  1232.     }
  1233.  
  1234.     /**
  1235.      * Overridden to make clone public.  Returns a shallow copy of this node;
  1236.      * the new node has no parent or children and has a reference to the same
  1237.      * user object, if any.
  1238.      *
  1239.      * @return    a copy of this node
  1240.      */
  1241.     public Object clone() {
  1242.     DefaultMutableTreeNode newNode = null;
  1243.  
  1244.     try {
  1245.         newNode = (DefaultMutableTreeNode)super.clone();
  1246.  
  1247.         // shallow copy -- the new node has no parent or children
  1248.         newNode.children = null;
  1249.         newNode.parent = null;
  1250.  
  1251.     } catch (CloneNotSupportedException e) {
  1252.         // Won't happen because we implement Cloneable
  1253.         throw new InternalError(e.toString());
  1254.     }
  1255.  
  1256.     return newNode;
  1257.     }
  1258.  
  1259.  
  1260.     // Serialization support.  
  1261.     private void writeObject(ObjectOutputStream s) throws IOException {
  1262.     Object[]             tValues;
  1263.  
  1264.     s.defaultWriteObject();
  1265.     // Save the userObject, if its Serializable.
  1266.     if(userObject != null && userObject instanceof Serializable) {
  1267.         tValues = new Object[2];
  1268.         tValues[0] = "userObject";
  1269.         tValues[1] = userObject;
  1270.     }
  1271.     else
  1272.         tValues = new Object[0];
  1273.     s.writeObject(tValues);
  1274.     }
  1275.  
  1276.     private void readObject(ObjectInputStream s) 
  1277.     throws IOException, ClassNotFoundException {
  1278.     Object[]      tValues;
  1279.  
  1280.     s.defaultReadObject();
  1281.  
  1282.     tValues = (Object[])s.readObject();
  1283.  
  1284.     if(tValues.length > 0 && tValues[0].equals("userObject"))
  1285.         userObject = tValues[1];
  1286.     }
  1287.  
  1288.     final class PreorderEnumeration implements Enumeration {
  1289.     protected Stack    stack;
  1290.  
  1291.     public PreorderEnumeration(TreeNode rootNode) {
  1292.         super();
  1293.         Vector v = new Vector(1);
  1294.         v.addElement(rootNode);    // PENDING: don't really need a vector
  1295.         stack = new Stack();
  1296.         stack.push(v.elements());
  1297.     }
  1298.  
  1299.     public boolean hasMoreElements() {
  1300.         return (!stack.empty() &&
  1301.             ((Enumeration)stack.peek()).hasMoreElements());
  1302.     }
  1303.  
  1304.     public Object nextElement() {
  1305.         Enumeration    enumer = (Enumeration)stack.peek();
  1306.         TreeNode    node = (TreeNode)enumer.nextElement();
  1307.         Enumeration    children = node.children();
  1308.  
  1309.         if (!enumer.hasMoreElements()) {
  1310.         stack.pop();
  1311.         }
  1312.         if (children.hasMoreElements()) {
  1313.         stack.push(children);
  1314.         }
  1315.         return node;
  1316.     }
  1317.  
  1318.     }  // End of class PreorderEnumeration
  1319.  
  1320.  
  1321.  
  1322.     final class PostorderEnumeration implements Enumeration {
  1323.     protected TreeNode root;
  1324.     protected Enumeration children;
  1325.     protected Enumeration subtree;
  1326.  
  1327.     public PostorderEnumeration(TreeNode rootNode) {
  1328.         super();
  1329.         root = rootNode;
  1330.         children = root.children();
  1331.         subtree = EMPTY_ENUMERATION;
  1332.     }
  1333.  
  1334.     public boolean hasMoreElements() {
  1335.         return root != null;
  1336.     }
  1337.  
  1338.     public Object nextElement() {
  1339.         Object retval;
  1340.  
  1341.         if (subtree.hasMoreElements()) {
  1342.         retval = subtree.nextElement();
  1343.         } else if (children.hasMoreElements()) {
  1344.         subtree = new PostorderEnumeration(
  1345.                 (TreeNode)children.nextElement());
  1346.         retval = subtree.nextElement();
  1347.         } else {
  1348.         retval = root;
  1349.         root = null;
  1350.         }
  1351.  
  1352.         return retval;
  1353.     }
  1354.  
  1355.     }  // End of class PostorderEnumeration
  1356.  
  1357.  
  1358.  
  1359.     final class BreadthFirstEnumeration implements Enumeration {
  1360.     protected Queue    queue;
  1361.  
  1362.     public BreadthFirstEnumeration(TreeNode rootNode) {
  1363.         super();
  1364.         Vector v = new Vector(1);
  1365.         v.addElement(rootNode);    // PENDING: don't really need a vector
  1366.         queue = new Queue();
  1367.         queue.enqueue(v.elements());
  1368.     }
  1369.  
  1370.     public boolean hasMoreElements() {
  1371.         return (!queue.isEmpty() &&
  1372.             ((Enumeration)queue.firstObject()).hasMoreElements());
  1373.     }
  1374.  
  1375.     public Object nextElement() {
  1376.         Enumeration    enumer = (Enumeration)queue.firstObject();
  1377.         TreeNode    node = (TreeNode)enumer.nextElement();
  1378.         Enumeration    children = node.children();
  1379.  
  1380.         if (!enumer.hasMoreElements()) {
  1381.         queue.dequeue();
  1382.         }
  1383.         if (children.hasMoreElements()) {
  1384.         queue.enqueue(children);
  1385.         }
  1386.         return node;
  1387.     }
  1388.  
  1389.  
  1390.     // A simple queue with a linked list data structure.
  1391.     final class Queue {
  1392.         QNode head;    // null if empty
  1393.         QNode tail;
  1394.  
  1395.         final class QNode {
  1396.         public Object    object;
  1397.         public QNode    next;    // null if end
  1398.         public QNode(Object object, QNode next) {
  1399.             this.object = object;
  1400.             this.next = next;
  1401.         }
  1402.         }
  1403.  
  1404.         public void enqueue(Object anObject) {
  1405.         if (head == null) {
  1406.             head = tail = new QNode(anObject, null);
  1407.         } else {
  1408.             tail.next = new QNode(anObject, null);
  1409.             tail = tail.next;
  1410.         }
  1411.         }
  1412.  
  1413.         public Object dequeue() {
  1414.         if (head == null) {
  1415.             throw new NoSuchElementException("No more elements");
  1416.         }
  1417.  
  1418.         Object retval = head.object;
  1419.         QNode oldHead = head;
  1420.         head = head.next;
  1421.         if (head == null) {
  1422.             tail = null;
  1423.         } else {
  1424.             oldHead.next = null;
  1425.         }
  1426.         return retval;
  1427.         }
  1428.  
  1429.         public Object firstObject() {
  1430.         if (head == null) {
  1431.             throw new NoSuchElementException("No more elements");
  1432.         }
  1433.  
  1434.         return head.object;
  1435.         }
  1436.  
  1437.         public boolean isEmpty() {
  1438.         return head == null;
  1439.         }
  1440.  
  1441.     } // End of class Queue
  1442.  
  1443.     }  // End of class BreadthFirstEnumeration
  1444.  
  1445.  
  1446.  
  1447.     final class PathBetweenNodesEnumeration implements Enumeration {
  1448.     protected Stack stack;
  1449.  
  1450.     public PathBetweenNodesEnumeration(TreeNode ancestor,
  1451.                        TreeNode descendant)
  1452.     {
  1453.         super();
  1454.  
  1455.         if (ancestor == null || descendant == null) {
  1456.         throw new IllegalArgumentException("argument is null");
  1457.         }
  1458.  
  1459.         TreeNode current;
  1460.  
  1461.         stack = new Stack();
  1462.         stack.push(descendant);
  1463.  
  1464.         current = descendant;
  1465.         while (current != ancestor) {
  1466.         current = current.getParent();
  1467.         if (current == null && descendant != ancestor) {
  1468.             throw new IllegalArgumentException("node " + ancestor +
  1469.                 " is not an ancestor of " + descendant);
  1470.         }
  1471.         stack.push(current);
  1472.         }
  1473.     }
  1474.  
  1475.     public boolean hasMoreElements() {
  1476.         return stack.size() > 0;
  1477.     }
  1478.  
  1479.     public Object nextElement() {
  1480.         try {
  1481.         return stack.pop();
  1482.         } catch (EmptyStackException e) {
  1483.         throw new NoSuchElementException("No more elements");
  1484.         }
  1485.     }
  1486.  
  1487.     } // End of class PathBetweenNodesEnumeration
  1488.  
  1489.  
  1490.  
  1491. } // End of class DefaultMutableTreeNode
  1492.